/*
** wopen.c
**
** Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits
** Redistributed by permission.
*/

#include <stdio.h>
#include <stdlib.h>
#include "pictor.h"


WINDOW *_PL_winhead = NULL;
int _PL_shadowcolor = foreback(WHITE,BLACK);


#define STATIC_BUFSIZ   4096
static char static_heap[STATIC_BUFSIZ];
static char *heap_base = static_heap;

/*
** Maintains and allocates from the static heap.
*/
static void *static_alloc(int size)
{
	if((heap_base + size) <= (static_heap + STATIC_BUFSIZ)) {
		heap_base += size;
		return(heap_base - size);
	}
	return(NULL);

} /* static_alloc */

/*
** Release static memory back to static heap.
*/
static void static_free(char *ptr)
{
	if(ptr >= static_heap && ptr < (static_heap + STATIC_BUFSIZ))
		heap_base = ptr;

} /* static_free */

/*
** Closes all open windows.
*/
void wcloseall(void)
{
	while(_PL_winhead != NULL)
		wclose();

} /* wcloseall */

/*
** Closes the current window.
*/
void wclose(void)
{
	WINDOW *win;
	int shadow;

	if(_PL_winhead != NULL) {

		win = _PL_winhead;
		_PL_winhead = _PL_winhead->next;

		shadow = (win->style & WO_SHADOW) ? 1 : 0;

		/* restore screen under window */
		if(win->buffer != NULL) {
			putscrn(win->buffer,win->top,win->left,win->height + shadow,
				win->width + shadow);

			/* release buffer memory */
			if(win->style & WO_STATICMEM)
				static_free((char *)win->buffer);
			else
				free(win->buffer);
		}
		/* restore cursor to previous window or full screen */
		setcurs(win->oldcurspos >> 8,win->oldcurspos & 0xFF);
		setcurstype(win->oldcurstype);

		if(win->style & WO_STATICMEM)
			static_free((char *)win);
		else
			free(win);
	}

} /* wclose */

/*
** Clears the current window pane.
*/
void wclear(void)
{
	if(_PL_winhead != NULL) {
		vcolor(_CURR_WPANE.color);
		scroll(0,_CURR_WPANE.top + 1,_CURR_WPANE.left + 1,getwrows(),getwcols());
		_CURR_WPANE.row = 0;
		_CURR_WPANE.column = 0;

		if(_PL_winhead->style & WO_TEXTCURSOR) {
			wsynccurs();
		}
	}

} /* wclear */

/*
** Defines and displays a window.
*/
int wopen(int top,int left,int height,int width,int color,int style)
{
	WINDOW *win;
	int i,shadow;

	shadow = (style & WO_SHADOW) ? 1 : 0;

	/* validate window coordinates */
	height = (height < 3) ? 3 : height;
	width = (width < 3) ? 3 : width;
	top = (top < 1) ? 1 : top;
	left = (left < 1) ? 1 : left;

	if(((top + height + shadow) - 1) > _PL_rows)
		height = (_PL_rows - (top + shadow)) + 1;
	if(((left + width + shadow) - 1) > _PL_columns)
		width = (_PL_columns - (left + shadow)) + 1;

	/* allocate memory for window */
	if(style & WO_STATICMEM) {
		/* allocate window structure */
		win = static_alloc(sizeof(WINDOW));
		if(win == NULL) {
			/* fatal error */
			_PL_color = 0x07;
			cls();
			vputs("Fatal error : wopen() out of static memory");
			exit(-1);
		}

		/* allocate window buffer */
		win->buffer = static_alloc(((height + shadow) * (width + shadow)) * 2);
	}
	else {
		/* allocate window structure */
		win = malloc(sizeof(WINDOW));
		if(win == NULL)
			return(FALSE);

		/* allocate window buffer */
		win->buffer = malloc(((height + shadow) * (width + shadow)) * 2);
		if(win->buffer == NULL) {
			free(win);
			return(FALSE);
		}
	}

	win->next = _PL_winhead;
	_PL_winhead = win;

	/* create the window */
	if(win->buffer != NULL)
		getscrn(win->buffer,top,left,height + shadow,width + shadow);
	vcolor(color);

	frame(top,left,height,width);

	/* create shadow */
	if(style & WO_SHADOW) {
		setvpos(top + height,left + 1);
		vrepa(_PL_shadowcolor,width);

		for(i = 0;i < height;i++) {
			setvpos(top + i + 1,left + width);
			vputa(_PL_shadowcolor);
		}
	}
	win->oldcurspos = getcurs();
	win->oldcurstype = getcurstype();
	win->top = top;
	win->left = left;
	win->height = height;
	win->width = width;
	win->style = style;
	win->color = color;

	win->numpanes = 1;
	win->currpane = 0;
	win->panes[win->currpane].top = top;
	win->panes[win->currpane].left = left;
	win->panes[win->currpane].height = height;
	win->panes[win->currpane].width = width;
	win->panes[win->currpane].color = color;

	if(win->style & WO_TEXTCURSOR)
		showcurs(TRUE);
	else
		setcurs(_PL_rows + 1,1);

	wclear();

	return(TRUE);

} /* wopen */
